import os
import time
from datetime import datetime
import logging
import bcrypt
import jwt
from typing import Dict, Optional
import secrets

from dotenv import load_dotenv, find_dotenv

from db.MySqlDB import MySQLDB
from utils.RequestTools import LoginRequest, RegisterRequest

load_dotenv(find_dotenv())

class UserAuthService:
    """用户认证服务类 - 处理用户注册和登录逻辑"""

    def __init__(self):
        self.mysqlDB = MySQLDB()
        # JWT密钥，实际项目中应从环境变量读取
        self.jwt_secret = os.getenv("JWT_SECRET")
        self.token_expiry_hours = 24

    def _generate_user_id(self) -> int:
        """生成用户ID"""
        return int(time.time() * 1000)

    def _hash_password(self, password: str) -> str:
        """对密码进行加密处理"""
        salt = bcrypt.gensalt()
        hashed = bcrypt.hashpw(password.encode('utf-8'), salt)
        return hashed.decode('utf-8')

    def _verify_password(self, plain_password: str, hashed_password: str) -> bool:
        """验证密码"""
        try:
            # 确保输入为bytes类型
            password_bytes = plain_password.encode('utf-8')
            hashed_bytes = hashed_password.encode('utf-8')

            # 使用bcrypt验证
            return bcrypt.checkpw(password_bytes, hashed_bytes)
        except Exception as e:
            logging.error(f"密码验证失败: {str(e)}")
            return False

    def _generate_token(self, user_id: str, username: str) -> str:
        """生成JWT token"""
        payload = {
            'user_id': user_id,
            'username': username,
            'exp': datetime.utcnow().timestamp() + self.token_expiry_hours * 3600,
            'iat': datetime.utcnow().timestamp()
        }
        return jwt.encode(payload, self.jwt_secret, algorithm='HS256')

    def _verify_token(self, token: str) -> Optional[Dict]:
        """验证JWT token"""
        try:
            payload = jwt.decode(token, self.jwt_secret, algorithms=['HS256'])
            return payload
        except jwt.ExpiredSignatureError:
            logging.error("Token已过期")
            return None
        except jwt.InvalidTokenError:
            logging.error("无效的Token")
            return None

    def user_register(self, register_data: RegisterRequest) -> Dict:
        """
        用户注册
        Args:
            register_data: 包含username, password, email, phone等字段的字典
        Returns:
            ApiResponse格式的响应
        """
        try:
            logging.info(f"开始用户注册: username={register_data.username}")

            username = register_data.username
            password = register_data.password
            email = register_data.email
            phone = register_data.phone

            # 检查用户名是否已存在
            check_sql = "SELECT id FROM t_user WHERE username = %s OR email = %s"
            check_params = (username, email)
            existing_user = self.mysqlDB.execute_query(check_sql, check_params)

            if existing_user:
                return {"code": 400, "message": "用户名或邮箱已存在", "data": None}

            # 加密密码
            hashed_password = self._hash_password(password)
            user_id = self._generate_user_id()
            print("userid=",int(user_id))
            current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

            # 插入用户数据
            insert_sql = """
                INSERT INTO t_user 
                (id, username, password, email, phone, created_at, updated_at) 
                VALUES (%s, %s, %s, %s, %s, %s, %s)
            """
            insert_params = (user_id, username, hashed_password, email, phone,
                             current_time, current_time)

            self.mysqlDB.execute_update(insert_sql, insert_params)
            logging.info(f"用户注册成功: user_id={user_id}")

            return {
                "code": 200,
                "message": "注册成功",
                "data": {"user_id": user_id, "username": username}
            }

        except Exception as e:
            logging.error(f"用户注册失败: {str(e)}")
            return {"code": 500, "message": f"注册失败: {str(e)}", "data": None}

    def user_login(self, login_data: LoginRequest) -> Dict:
        """
        用户登录
        Args:
            login_data: 包含username和password的字典
        Returns:
            ApiResponse格式的响应，包含token和用户信息
        """
        try:
            logging.info(f"用户登录尝试: username={login_data.username}")

            username = login_data.username
            password = login_data.pwd
            if not username or not password:
                return {"code": 400, "message": "用户名和密码不能为空", "data": None}

            # 查询用户信息
            sql = """
                SELECT id, username, password, email, phone, status, role 
                FROM t_user 
                WHERE username = %s
            """
            params = (username, )
            result = self.mysqlDB.execute_query(sql, params)

            if not result:
                return {"code": 401, "message": "用户名或密码错误", "data": None}

            user = result[0]

            print("user:", user)
            # 检查用户状态
            if user['status'] != 'active':
                return {"code": 403, "message": "账户已被禁用，请联系管理员", "data": None}

            # 验证密码
            if not self._verify_password(password, user['password']):
                return {"code": 401, "message": "用户名或密码错误", "data": None}
            # 生成token
            token = self._generate_token(user['id'], user['username'])

            # 更新最后登录时间
            self._update_last_login(user['id'])

            logging.info(f"用户登录成功: user_id={user['id']}")

            user_info = {
                "user_id": user['id'],
                "username": user['username'],
                "email": user['email'],
                "phone": user.get('phone', ''),
                "role": user['role'],
                "token": token
            }

            return {"code": 200, "message": "登录成功", "data": user_info}

        except Exception as e:
            logging.error(f"用户登录失败: {str(e)}")
            return {"code": 500, "message": f"登录失败: {str(e)}", "data": None}

    def _update_last_login(self, user_id: str):
        """更新最后登录时间"""
        try:
            update_sql = "UPDATE t_user SET last_login = %s WHERE id = %s"
            update_params = (datetime.now().strftime("%Y-%m-%d %H:%M:%S"), user_id)
            self.mysqlDB.execute_update(update_sql, update_params)
        except Exception as e:
            logging.error(f"更新最后登录时间失败: {str(e)}")

    def verify_token(self, token: str) -> Dict:
        """验证token有效性"""
        try:
            payload = self._verify_token(token)
            if not payload:
                return {"code": 401, "message": "无效的token", "data": None}

            # 检查用户是否存在且活跃
            sql = "SELECT id, username, status FROM t_user WHERE id = %s"
            result = self.mysqlDB.execute_query(sql, (payload['user_id'],))

            if not result or result[0]['status'] != 'active':
                return {"code": 401, "message": "用户不存在或已被禁用", "data": None}

            return payload

        except Exception as e:
            logging.error(f"token验证失败: {str(e)}")
            return {"code": 401, "message": "token验证失败", "data": None}

    def get_user_info(self, user_id: str) -> Dict:
        """获取用户信息（不包含密码）"""
        try:
            sql = """
                SELECT id, username, email, phone, status, role, 
                       created_at, last_login 
                FROM t_user WHERE id = %s
            """
            result = self.mysqlDB.execute_query(sql, (user_id,))

            if not result:
                return {"code": 404, "message": "用户不存在", "data": None}

            return {"code": 200, "message": "获取成功", "data": result[0]}

        except Exception as e:
            logging.error(f"获取用户信息失败: {str(e)}")
            return {"code": 500, "message": f"获取用户信息失败: {str(e)}", "data": None}